package com.xjh.service.impl;

import com.alibaba.fastjson.JSON;
import com.xjh.mapper.StudentDynamicDynamicSqlSupport;
import com.xjh.mapper.StudentDynamicMapper;
import com.xjh.mapper.xjhTableDynamicSqlSupport;
import com.xjh.mapper.xjhTableMapper;
import com.xjh.po.StudentDynamic;
import com.xjh.po.xjhTable;
import com.xjh.service.TestDynamicSqlService;
import com.xjh.utils.util.id.snowflake.IDWorker;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.IEEE754rUtils;
import org.hamcrest.core.IsEqual;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.where.condition.IsEqualTo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

import static com.xjh.mapper.StudentDynamicDynamicSqlSupport.studentDynamic;
import static org.mybatis.dynamic.sql.SqlBuilder.*;

/**
 * @author XuJianHua
 * @date 2022-09-13 15:46:28
 * @description
 */
@Service
public class TestDynamicSqlImpl implements TestDynamicSqlService {
    @Autowired
    private xjhTableMapper xjhTableMapper;

    @Autowired
    private StudentDynamicMapper studentDynamicMapper;

   /**
    @author XuJianHua
    @date 2022/9/14 13:58
    @description  增删查改都可以通过SqlBuilder/DSLCompleter两种方式进行。
    后者Completer 的写法更简洁，但是不能自定义返回字段（单表操作使用Comlpter,多表查询用SqlBuilder（可以自定义返回字段））
    Completer 可以转 Provider。SelectDSLCompleter 的底层最终还是使用的是 Provider ，即 Provider 才是根本。
    1.SqlBuilder 类构建 StatementProvider
    @return
   */
    @Override
    public List<xjhTable> test() {
        StudentDynamic studentDynamic1 = new StudentDynamic();
        studentDynamic1.setStuName("建华");
        /**1.根据id查询:不加.get()时得到的是一个optional对象，此时可用ifPresent判空*/
        xjhTable xjhTable1 = xjhTableMapper.selectByPrimaryKey(1L).get();
        System.out.println("根据id查询===" + xjhTable1.toString());
        /**1.根据条件构造器查询：参数是条件构造器*/
        xjhTable xjhTable2 = new xjhTable();
        xjhTable2.setStuId(2L);
        List<Long> ids = Arrays.asList(1L, 2L);
        List<xjhTable> xjhTables = xjhTableMapper.selectMany(
                // 可以手动选择来自多个表的字段
//                select(xjhTableDynamicSqlSupport.id,StudentDynamicDynamicSqlSupport.stuName)
//                选择一个表的所有字段，此时不适用于有join的查询
                select(xjhTableMapper.selectList)
                        .from(xjhTableDynamicSqlSupport.xjhTable)
                        // 多表链接：.leftJoin(需要连接的表Support.驼峰表名).on(该表的连接字段，equalTo(本表的字段))
                        .leftJoin(studentDynamic).on(StudentDynamicDynamicSqlSupport.id, equalTo(xjhTableDynamicSqlSupport.stuId))

                        // 可以使用and拼接多个条件
                        .where(xjhTableDynamicSqlSupport.stuId, isEqualTo(2L))
                        // 不等于
                        .and(xjhTableDynamicSqlSupport.stuId, isNotEqualTo(3213242L))
                        // in条件，参数是list集合
                        .and(xjhTableDynamicSqlSupport.id, isIn(ids))
                        // like 用做筛选条件，当为空时，不设置该条件（动态sql） 老版本用法(当name不为空时，把like条件两边加上%)
//                        .and(StudentDynamicDynamicSqlSupport.stuName, isLike(studentDynamic1.getStuName()).when(StringUtils::isNotBlank).then(s -> "%" + s + "%"))
                        //动态sql 当内部为null时不添加此条件，注意此时不能加%，否则就不为null了，变成%null，isLikeWhenPresent失效
//                        .and(StudentDynamicDynamicSqlSupport.stuName, isLikeWhenPresent(studentDynamic1.getStuName()))
                        //对于筛选条件 老版本用when和then  新版本用filter和map
                        .and(StudentDynamicDynamicSqlSupport.stuName, isLike(studentDynamic1.getStuName()).filter(StringUtils::isNoneBlank).map(s -> "%" + s + "%"))
                        // 1.4最终版 (因为判断的是object==null,所以无法判断“”，1.1可以用then,效果也是一样)
                        .and(StudentDynamicDynamicSqlSupport.stuName, isLikeWhenPresent(studentDynamic1.getStuName()).map(s -> "%" + s + "%"))
                        // like 用作正常查询
//                        .and(StudentDynamicDynamicSqlSupport.stuName, isLike("张%"))
                        // 某个字段为空/不为空
                        .and(xjhTableDynamicSqlSupport.createBy, isNull())
                        .and(xjhTableDynamicSqlSupport.id, isNotNull())
                        // 排序字段
                        .orderBy(xjhTableDynamicSqlSupport.id)
                        .build()
                        .render(RenderingStrategies.MYBATIS3));
        System.out.println("根据条件构造器查询===" + xjhTables);
        /**通过DSL来查询*/
       xjhTableMapper.select(dsl -> dsl
                .leftJoin(studentDynamic)
                .on(StudentDynamicDynamicSqlSupport.id, equalTo(xjhTableDynamicSqlSupport.stuId))
                .where(xjhTableDynamicSqlSupport.id, isEqualTo(999L)));

        /**2.insert单条数据*/
        xjhTable xjhTable = new xjhTable();
        xjhTable.setId(IDWorker.generateId());
        xjhTable.setMoney(new BigDecimal("33"));
//        xjhTableMapper.insert(xjhTable);
        // 使用这个比较靠谱
        xjhTableMapper.insertSelective(xjhTable);

        /**2.insert批量数据*/
        List<xjhTable> objects = new ArrayList<>();
        objects.add(xjhTable);
//        int i1 = xjhTableMapper.insertMultiple(objects);
//        System.out.println("insert批量数据" + i1);


        /**2.delete单条数据*/
        // 根据主键删除
        int i = xjhTableMapper.deleteByPrimaryKey(11L);
        // 使用DeleteDSLCompleter进行删除操作（写法较为简单）
        int delete1 = xjhTableMapper.delete(dsl -> dsl.where(xjhTableDynamicSqlSupport.id, isEqualTo(999L)));

        // 根据条件删除
        int delete = xjhTableMapper.delete(deleteFrom(xjhTableDynamicSqlSupport.xjhTable)
                .where(xjhTableDynamicSqlSupport.money, isEqualTo(new BigDecimal(23)))
                .build()
                .render(RenderingStrategies.MYBATIS3));
        System.out.println("根据条件删除" + delete);

        /**2.更新单条数据*/
        /*insertSelective 对应的 SQL 语句加入了 NULL 检验，只会插入数据不为 null 的字段，而 insert会插入所有字段，会插入 null 数据。
        也就意味着如果定义了表 default 字段，使用 insert 还是会插入 null 而忽略 default*/
        int i2 = xjhTableMapper.updateByPrimaryKeySelective(xjhTable);

        /**2.批量更新*/
        xjhTableMapper.update(dsl -> dsl
                .set(xjhTableDynamicSqlSupport.updateTime).equalTo(new Date())
                .where(
                        xjhTableDynamicSqlSupport.id, isEqualTo(999L))
                .and(xjhTableDynamicSqlSupport.id, isEqualTo(999L))
        );
        /**2.案例（1对1）：查询所有xjhTable,同时根据其stu_id ,查询出StudentDynamic的信息，封装到xjhTable实体中的list中*/
       List<xjhTable> list = xjhTableMapper.findAll();
        System.out.println("注解1对1查询==="+ JSON.toJSONString(list));
        return xjhTables;
    }
}
